package com.aizuda.boot.modules.business.approval.service.impl;

import com.aizuda.boot.modules.business.approval.entity.HandoverHistory;
import com.aizuda.boot.modules.business.approval.entity.dto.HandoverDTO;
import com.aizuda.boot.modules.business.approval.entity.dto.QueryHandoverDTO;
import com.aizuda.boot.modules.business.approval.entity.dto.QueryHandoverHistoryDTO;
import com.aizuda.boot.modules.business.approval.entity.vo.HandoverHistoryVO;
import com.aizuda.boot.modules.business.approval.entity.vo.HandoverQueryVO;
import com.aizuda.boot.modules.business.approval.mapper.HandoverHistoryMapper;
import com.aizuda.boot.modules.business.approval.service.HandoverService;
import com.aizuda.boot.modules.business.contract.dto.SingleResponse;
import com.aizuda.boot.modules.business.contract.entity.ContractWorkflowEntity;
import com.aizuda.boot.modules.business.contract.service.ContractWorkflowService;
import com.aizuda.boot.modules.common.constant.enums.ResponseCodeEnum;
import com.aizuda.boot.modules.business.contract.util.AuthUtil;
import com.aizuda.boot.modules.business.permission.domain.response.EmployeeShowVO;
import com.aizuda.boot.modules.common.constant.enums.WorkflowTypeEnum;


import com.aizuda.boot.modules.system.entity.SysUser;
import com.aizuda.boot.modules.system.service.ISysUserService;
import com.aizuda.bpm.engine.FlowLongEngine;
import com.aizuda.bpm.engine.TaskService;
import com.aizuda.bpm.engine.core.FlowCreator;
import com.aizuda.bpm.engine.core.FlowLongContext;
import com.aizuda.bpm.engine.core.enums.TaskType;
import com.aizuda.bpm.engine.entity.*;
import com.aizuda.bpm.engine.model.*;
import com.aizuda.bpm.mybatisplus.mapper.*;
import com.aizuda.service.spring.SpringHelper;
import com.aizuda.service.web.UserSession;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 审批交接服务实现类
 * <p>
 * 支持三种类型的任务分别交接：
 * 1. 包含用户的流程定义（第一类）：流程定义中包含该用户作为审批人的流程
 * 2. 用户发起的流程实例（第二类）：用户创建/发起的流程实例
 * 3. 用户待办任务（第三类）：需要用户审批的待处理任务
 * <p>
 * 查询时会全部查询三种类型，交接时可以分别交接或部分交接
 *
 * @Author sangyirong
 * @ClassName HandoverServiceImpl
 * @Version 1.0
 * @Date 2025/7/24 19:10
 */
@Slf4j
@Service
public class HandoverServiceImpl extends ServiceImpl<HandoverHistoryMapper, HandoverHistory> implements HandoverService {

    // 常量定义
    private static final Integer ACTOR_TYPE_USER = 0;

    // 缓存流程模型解析结果，避免重复解析
    private final Map<Long, ProcessModel> processModelCache = new ConcurrentHashMap<>();

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private FlwTaskActorMapper flwTaskActorMapper;

    @Resource
    private FlwInstanceMapper flwInstanceMapper;

    @Resource
    private FlwProcessMapper flwProcessMapper;


    @Resource
    private FlwTaskMapper flwTaskMapper;

    @Resource
    private HandoverHistoryMapper handoverHistoryMapper;

    @Resource
    private FlwExtInstanceMapper flwExtInstanceMapper;

    @Resource
    private ContractWorkflowService contractWorkflowService;

    @Resource
    private FlwHisInstanceMapper flwHisInstanceMapper;

    @Override
    public SingleResponse<IPage<HandoverHistoryVO>> history(QueryHandoverHistoryDTO dto) {
        if (null == dto || null == dto.getPageNo() || dto.getPageNo() < 1 || null == dto.getPageSize() || dto.getPageSize() < 1) {
            return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), "分页参数不合法");
        }
        Page<HandoverHistory> page = new Page<>(dto.getPageNo(), dto.getPageSize());
        LambdaQueryWrapper<HandoverHistory> wrapper = new LambdaQueryWrapper<>();
        if (null != dto.getOperateStartTime()) {
            wrapper.ge(HandoverHistory::getCreateTime, dto.getOperateStartTime());
        }
        if (null != dto.getOperateEndTime()) {
            wrapper.le(HandoverHistory::getCreateTime, dto.getOperateEndTime());
        }
        if (null != dto.getOperateUser()) {
            wrapper.eq(HandoverHistory::getCreateId, dto.getOperateUser());
        }
        wrapper.orderByDesc(HandoverHistory::getCreateTime);
        baseMapper.selectPage(page, wrapper);

        List<HandoverHistory> historyList = page.getRecords();
        if (CollectionUtils.isEmpty(historyList)) {
            return SingleResponse.of(new Page<>());
        }
        HashSet<Long> userIds = new HashSet<>();
        historyList.forEach(item -> {
            userIds.add(item.getHandoverUser());
            userIds.add(item.getHeirUser());
            userIds.add(item.getCreateId());
        });
        Map<Long, EmployeeShowVO> userMap = sysUserService.lambdaQuery()
                .in(SysUser::getId, userIds)
                .select(SysUser::getId, SysUser::getNickName, SysUser::getAvatar)
                .list()
                .stream().map(item -> {
                    EmployeeShowVO employeeShowVO = new EmployeeShowVO();
                    employeeShowVO.setId(item.getId());
                    employeeShowVO.setName(item.getNickName());
                    employeeShowVO.setAvatar(item.getAvatar());
                    return employeeShowVO;
                }).collect(Collectors.toMap(EmployeeShowVO::getId, item -> item));
        List<HandoverHistoryVO> handoverHistoryVOS = historyList.stream().map(item -> {
            HandoverHistoryVO vo = new HandoverHistoryVO();
            BeanUtils.copyProperties(item, vo);
            vo.setHandoverUser(userMap.get(item.getHandoverUser()));
            vo.setHeirUserName(userMap.get(item.getHeirUser()));
            vo.setCreateUser(userMap.get(item.getCreateId()));
            return vo;
        }).collect(Collectors.toList());
        Page<HandoverHistoryVO> result = new Page<>(dto.getPageNo(), dto.getPageSize());
        result.setRecords(handoverHistoryVOS);
        result.setTotal(page.getTotal());
        // 注意：setPages方法已废弃，但为保持兼容性暂时保留
        @SuppressWarnings("deprecation")
        long pages = page.getPages();
        result.setPages(pages);
        result.setSize(page.getSize());
        result.setCurrent(page.getCurrent());

        return SingleResponse.of(result);
    }

    /**
     * 查询审批交接列表
     *
     * @param dto 查询参数
     * @return 交接查询结果
     */
    @Override
    public SingleResponse<List<HandoverQueryVO>> query(QueryHandoverDTO dto) {
        long startTime = System.currentTimeMillis();

        try {
            // 1. 参数校验
            if (null == dto || null == dto.getHandoverUser()) {
                log.warn("参数校验失败: dto={}", dto);
                return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(),
                        ResponseCodeEnum.PARAMETER_ERROR.getMsg());
            }

            log.info("开始查询用户[{}]的审批交接列表, 指定分类: {}",
                    dto.getHandoverUser(), dto.getWorkflowType());
            if (CollectionUtils.isEmpty(dto.getWorkflowType())) {
                dto.setWorkflowType(Arrays.stream(WorkflowTypeEnum.values())
                        .map(WorkflowTypeEnum::getCode)
                        .collect(Collectors.toList()));
            }

            // 2. 获取流程配置信息
            Map<String, List<FlwProcess>> processTypeMap = getProcess(dto.getWorkflowType());
            if (CollectionUtils.isEmpty(processTypeMap)) {
                log.info("未找到匹配的流程配置, 分类ID: {}", dto.getWorkflowType());
                return SingleResponse.of(new ArrayList<>());
            }

            // 3. 预取用户相关任务/实例，减少重复数据库访问
            QueryPrefetchContext prefetchContext = buildQueryPrefetchContext(dto.getHandoverUser(), processTypeMap);

            // 4. 构建交接查询结果（使用预取数据）
            List<HandoverQueryVO> results = buildHandoverQueryResults(
                    dto.getHandoverUser(), processTypeMap, prefetchContext);

            long totalTime = System.currentTimeMillis() - startTime;
            log.info("查询完成, 用户[{}]共有{}个分类可交接, 总耗时: {}ms",
                    dto.getHandoverUser(), results.size(), totalTime);

            return SingleResponse.of(results);

        } catch (Exception e) {
            long totalTime = System.currentTimeMillis() - startTime;
            log.error("查询审批交接列表异常, 用户ID: {}, 耗时: {}ms", dto.getHandoverUser(), totalTime, e);
            return SingleResponse.failure(ResponseCodeEnum.ERROR.getCode(), ResponseCodeEnum.ERROR.getMsg());
        }
    }

    /**
     * 预取当前查询所需的用户任务/实例数据，避免在每个类型下重复查询
     */
    private QueryPrefetchContext buildQueryPrefetchContext(Long userId,
                                                           Map<String, List<FlwProcess>> processTypeMap) {
        QueryPrefetchContext context = new QueryPrefetchContext();

        // 汇总所有流程ID（用于一次性范围查询）
        context.allProcessIds = processTypeMap.values().stream()
                .filter(list -> !CollectionUtils.isEmpty(list))
                .flatMap(list -> list.stream().map(FlwProcess::getId))
                .collect(Collectors.toSet());

        // 1) 预取用户作为参与者的任务链路：Actor -> Task -> Instance
        context.taskActors = flwTaskActorMapper.selectList(Wrappers.<FlwTaskActor>lambdaQuery()
                .eq(FlwTaskActor::getActorType, ACTOR_TYPE_USER)
                .eq(FlwTaskActor::getActorId, userId));

        if (!CollectionUtils.isEmpty(context.taskActors)) {
            List<Long> taskIds = context.taskActors.stream()
                    .map(FlwTaskActor::getTaskId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());

            if (!CollectionUtils.isEmpty(taskIds)) {
                context.tasksFromActors = flwTaskMapper.selectList(Wrappers.<FlwTask>lambdaQuery()
                        .in(FlwTask::getId, taskIds));
            }

            if (!CollectionUtils.isEmpty(context.tasksFromActors)) {
                List<Long> instanceIds = context.tasksFromActors.stream()
                        .map(FlwTask::getInstanceId)
                        .filter(Objects::nonNull)
                        .distinct()
                        .collect(Collectors.toList());

                if (!CollectionUtils.isEmpty(instanceIds)) {
                    context.instancesFromTasks = flwInstanceMapper.selectList(Wrappers.<FlwInstance>lambdaQuery()
                            .in(FlwInstance::getId, instanceIds));
                }
            }
        }

        // 2) 预取用户发起的实例（限定在本次涉及的流程范围内）
        if (!CollectionUtils.isEmpty(context.allProcessIds)) {
            context.userInitiatedInstancesAll = flwInstanceMapper.selectList(Wrappers.<FlwInstance>lambdaQuery()
                    .in(FlwInstance::getProcessId, context.allProcessIds)
                    .eq(FlwInstance::getCreateId, userId));
        }

        // 目前不需要构建额外索引

        return context;
    }

    private Map<String, List<FlwProcess>> getProcess(List<String> workflowType) {
        LambdaQueryWrapper<ContractWorkflowEntity> wrapper = new LambdaQueryWrapper<>();
        if (!CollectionUtils.isEmpty(workflowType)) {
            wrapper.in(ContractWorkflowEntity::getWorkflowType, workflowType);
        }
        List<ContractWorkflowEntity> list = contractWorkflowService.list(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return new HashMap<>();
        }

        List<String> processKey = list.stream().map(ContractWorkflowEntity::getProcessKey).distinct().toList();
        if (CollectionUtils.isEmpty(processKey)) {
            return new HashMap<>();
        }

        // 查询所有相关的流程定义
        List<FlwProcess> processList = flwProcessMapper.selectList(Wrappers.<FlwProcess>lambdaQuery()
                .in(FlwProcess::getProcessKey, processKey));

        if (CollectionUtils.isEmpty(processList)) {
            return new HashMap<>();
        }

        // 按processKey分组FlwProcess
        Map<String, List<FlwProcess>> processKeyMap = processList.stream()
                .collect(Collectors.groupingBy(FlwProcess::getProcessKey));

        // 创建workflowType到processKey的映射
        Map<String, Set<String>> workflowToProcessKeyMap = list.stream()
                .collect(Collectors.groupingBy(
                        ContractWorkflowEntity::getWorkflowType,
                        Collectors.mapping(ContractWorkflowEntity::getProcessKey, Collectors.toSet())
                ));

        // 构建最终结果：workflowType -> List<FlwProcess>
        Map<String, List<FlwProcess>> result = new HashMap<>();
        for (Map.Entry<String, Set<String>> entry : workflowToProcessKeyMap.entrySet()) {
            String type = entry.getKey();
            Set<String> keys = entry.getValue();

            List<FlwProcess> processes = new ArrayList<>();
            for (String key : keys) {
                List<FlwProcess> keyProcesses = processKeyMap.get(key);
                if (!CollectionUtils.isEmpty(keyProcesses)) {
                    processes.addAll(keyProcesses);
                }
            }

            if (!CollectionUtils.isEmpty(processes)) {
                result.put(type, processes);
            }
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SingleResponse<Void> handover(HandoverDTO dto) {
        if (!AuthUtil.isSuperAdmin()) {
            return SingleResponse.failure(ResponseCodeEnum.HAVE_NO_PERMISSION.getCode(), ResponseCodeEnum.HAVE_NO_PERMISSION.getMsg());
        }
        if (null == dto || null == dto.getHandoverUser() || null == dto.getHeirUser()) {
            return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
        }
        if (dto.getHandoverUser().equals(dto.getHeirUser())) {
            return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
        }
        if (CollectionUtils.isEmpty(dto.getHandoverVOList())) {
            log.info("交接内容为空");
            return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
        }
        try {
            log.info("开始执行交接操作: 交接人[{}] -> 继承人[{}], 涉及{}个分类",
                    dto.getHandoverUser(), dto.getHeirUser(), dto.getHandoverVOList().size());
            Long handoverUserId = dto.getHandoverUser();
            SysUser handoverUser = sysUserService.getById(handoverUserId);
            if (null == handoverUser) {
                log.warn("交接人[{}]不存在", handoverUserId);
                return SingleResponse.failure(ResponseCodeEnum.USER_DOES_NOT_EXIST.getCode(), ResponseCodeEnum.USER_DOES_NOT_EXIST.getMsg());
            }
            FlowCreator handoverFlowCreator = FlowCreator.of(String.valueOf(handoverUser.getId()), handoverUser.getNickName());
            Long heirUserId = dto.getHeirUser();
            SysUser heirUserInfo = sysUserService.getById(heirUserId);
            if (null == heirUserInfo) {
                log.warn("继承人[{}]不存在", heirUserId);
                return SingleResponse.failure(ResponseCodeEnum.USER_DOES_NOT_EXIST.getCode(), ResponseCodeEnum.USER_DOES_NOT_EXIST.getMsg());
            }
            FlowCreator heirFlowCreator = FlowCreator.of(String.valueOf(heirUserInfo.getId()), heirUserInfo.getNickName());
            String reason = dto.getReason();
            // dto.getHandoverQueryVOList();  // 未使用，移除以消除告警
            List<HandoverDTO.HandoverVO> handoverVOList = dto.getHandoverVOList();

            int successCount = 0;
            int totalCount = handoverVOList.size();

            for (HandoverDTO.HandoverVO handoverVO : handoverVOList) {
                try {
                    log.info("开始交接分类[{}]", handoverVO.getWorkFlowType());

                    // 分别处理三种类型的任务交接，支持独立交接
                    int pendingTaskCount = 0;
                    int initiatedInstanceCount = 0;
                    int containUserProcessCount = 0;

                    // 1. 交接用户待办任务
                    if (!CollectionUtils.isEmpty(handoverVO.getTaskId())) {
                        pendingTaskCount = handlePendingTasksHandover(handoverVO.getTaskId(), handoverFlowCreator, heirFlowCreator);
                        log.info("分类[{}] - 用户待办任务交接完成，成功交接{}个", handoverVO.getWorkFlowType(), pendingTaskCount);
                    }

                    // 2. 交接用户发起的流程实例
                    if (!CollectionUtils.isEmpty(handoverVO.getInstanceId())) {
                        initiatedInstanceCount = handleInitiatedInstancesHandover(handoverVO.getInstanceId(), heirFlowCreator);
                        log.info("分类[{}] - 用户发起的流程实例交接完成，成功交接{}个", handoverVO.getWorkFlowType(), initiatedInstanceCount);
                    }

                    // 3. 交接包含用户的流程
                    if (!CollectionUtils.isEmpty(handoverVO.getProcessId())) {
                        containUserProcessCount = handleContainUserProcessHandover(handoverVO.getProcessId(), handoverFlowCreator, heirFlowCreator);
                        log.info("分类[{}] - 包含用户的流程交接完成，成功交接{}个", handoverVO.getWorkFlowType(), containUserProcessCount);
                    }

                    // 4. 计算实际交接的任务总数
                    int totalHandoverCount = pendingTaskCount + initiatedInstanceCount + containUserProcessCount;

                    // 5. 只有在实际有成功交接的任务时才保存交接历史
                    if (totalHandoverCount > 0) {
                        saveHandoverHistory(handoverVO, reason, handoverUserId, heirUserId, pendingTaskCount, initiatedInstanceCount, containUserProcessCount);
                        log.info("分类[{}]交接历史已保存 - 总交接数:{}", handoverVO.getWorkFlowType(), totalHandoverCount);
                    } else {
                        log.info("分类[{}]无实际交接内容，不保存交接历史", handoverVO.getWorkFlowType());
                    }
                    successCount++;
                    log.info("分类[{}]交接完成 - 待办任务:{}, 发起实例:{}, 流程定义:{}",
                            handoverVO.getWorkFlowType(), pendingTaskCount, initiatedInstanceCount, containUserProcessCount);
                }catch (Exception e){
                    log.error("分类[{}]交接异常", handoverVO.getWorkFlowType(), e);
                }
            }

            // 清除缓存的模型缓存
            processModelCache.clear();
            log.info("交接操作完成: 成功{}/总计{}个分类", successCount, totalCount);

        } catch (Exception e) {
            log.error("处理交接异常", e);
            return SingleResponse.failure(ResponseCodeEnum.SYS_ERROR.getCode(), ResponseCodeEnum.SYS_ERROR.getMsg());
        }


        return SingleResponse.of(null);
    }

    /**
     * 保存交接历史
     *
     * @param vo
     * @param reason
     * @param handoverUserId
     * @param heirUserId
     * @param pendingTaskCount        实际交接的待办任务数
     * @param initiatedInstanceCount  实际交接的发起实例数
     * @param containUserProcessCount 实际交接的包含用户流程数
     */
    private void saveHandoverHistory(HandoverDTO.HandoverVO vo, String reason, Long handoverUserId, Long heirUserId,
                                     int pendingTaskCount, int initiatedInstanceCount, int containUserProcessCount) {
        // 由工作流类型推断分类名称（放在try外，供日志使用）
        String categoryName = Arrays.stream(WorkflowTypeEnum.values())
                .filter(e -> e.getCode().equals(vo.getWorkFlowType()))
                .map(WorkflowTypeEnum::getMsg)
                .findFirst()
                .orElse(vo.getWorkFlowType());
        try {
            HandoverHistory handoverHistory = new HandoverHistory();
            UserSession loginInfo = UserSession.getLoginInfo();
            handoverHistory.setApprovalName(categoryName);
            handoverHistory.setHandoverUser(handoverUserId);
            handoverHistory.setHeirUser(heirUserId);
            handoverHistory.setReason(reason);
            handoverHistory.setContent(buildContent(categoryName, handoverUserId, heirUserId, pendingTaskCount, initiatedInstanceCount, containUserProcessCount));
            handoverHistory.setCreateId(loginInfo.getId());
            handoverHistory.setCreateBy(loginInfo.getUsername());
            handoverHistory.setStatus(1);
            handoverHistory.setCreateTime(new Date());

            int insertCount = handoverHistoryMapper.insert(handoverHistory);
            if (insertCount > 0) {
                log.info("交接历史记录保存成功，分类[{}]", categoryName);
            } else {
                log.warn("交接历史记录保存失败，分类[{}]", categoryName);
            }
        } catch (Exception e) {
            log.error("保存交接历史记录失败，分类[{}]", categoryName, e);
        }
    }

    private String buildContent(String categoryName, Long handoverUserId, Long heirUserId,
                                int pendingTaskCount, int initiatedInstanceCount, int containUserProcessCount) {
        StringBuilder content = new StringBuilder();

        // 获取用户信息
        SysUser handoverUser = sysUserService.getById(handoverUserId);
        SysUser heirUser = sysUserService.getById(heirUserId);

        String handoverUserName = handoverUser != null ? handoverUser.getNickName() : "未知用户";
        String heirUserName = heirUser != null ? heirUser.getNickName() : "未知用户";

        // 构建基本信息
        content.append("交接人：").append(handoverUserName)
                .append("，被交接人：").append(heirUserName)
                .append("，流程分类：").append(categoryName)
                .append("。");

        // 使用实际交接的任务数量
        if (containUserProcessCount > 0 || initiatedInstanceCount > 0 || pendingTaskCount > 0) {
            content.append("交接内容包括：");

            List<String> items = new ArrayList<>();
            if (containUserProcessCount > 0) {
                items.add("包含用户的流程定义" + containUserProcessCount + "个");
            }
            if (initiatedInstanceCount > 0) {
                items.add("用户发起的实例" + initiatedInstanceCount + "个");
            }
            if (pendingTaskCount > 0) {
                items.add("用户待办任务" + pendingTaskCount + "个");
            }

            content.append(String.join("，", items)).append("。");
        } else {
            content.append("无实际交接内容。");
        }

        return content.toString();
    }

    /**
     * 交接包含该用户的流程定义
     *
     * @param containUserProcesses
     * @param handoverFlowCreator
     * @param heirFlowCreator
     * @return 实际成功交接的流程定义数量
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public int handleContainUserProcessHandover(List<Long> containUserProcesses, FlowCreator handoverFlowCreator, FlowCreator heirFlowCreator) {
        if (CollectionUtils.isEmpty(containUserProcesses)) {
            log.info("没有包含该用户的流程定义");
            return 0;
        }

        String handoverUserId = handoverFlowCreator.getCreateId();
        String heirUserId = heirFlowCreator.getCreateId();

        log.info("开始交接包含用户的流程定义，交接人[{}] -> 继承人[{}]，涉及{}个流程",
                handoverUserId, heirUserId, containUserProcesses.size());

        int successCount = 0;
        for (Long processId : containUserProcesses) {
            try {
                log.info("开始处理流程定义[{}]", processId);

                // 1. 更新流程定义模型中的所有交接用户
                boolean processModelUpdated = updateProcessDefinitionModel(processId, handoverUserId, heirUserId, heirFlowCreator);

                // 2. 更新该流程所有正在执行实例模型中的所有交接用户
                boolean instancesUpdated = updateAllRunningInstancesModel(processId, handoverUserId, heirUserId, heirFlowCreator);
                if (processModelUpdated && instancesUpdated) {
                    log.info("流程定义[{}]交接成功", processId);
                    successCount++;
                }


            } catch (Exception e) {
                log.error("交接流程定义[{}]失败", processId, e);
            }
        }

        log.info("包含用户的流程定义交接完成，成功交接{}个流程", successCount);
        return successCount;
    }

    /**
     * 更新流程定义模型中的所有交接用户
     *
     * @return 是否成功更新
     */
    private boolean updateProcessDefinitionModel(Long processId, String handoverUserId, String heirUserId, FlowCreator heirFlowCreator) {
        try {
            FlwProcess process = flwProcessMapper.selectById(processId);
            if (process == null || process.getModelContent() == null) {
                log.warn("流程定义[{}]不存在或模型内容为空", processId);
                return false;
            }

            log.info("开始更新流程定义[{}]模型，交接人[{}] -> 继承人[{}]",
                    processId, handoverUserId, heirUserId);

            // 使用ModelHelper解析流程模型
            ProcessModel processModel = ModelHelper.buildProcessModel(process.getModelContent());
            NodeModel rootNode = processModel.getNodeConfig();

            // 先验证交接用户是否确实存在于该流程中（与query方法保持一致的逻辑）
            Long handoverUserIdLong = Long.valueOf(handoverUserId);
            if (!isContainUser(rootNode, handoverUserIdLong)) {
                log.warn("流程定义[{}]中不包含交接用户[{}]，跳过交接", processId, handoverUserId);
                return false;
            }

            log.info("验证通过：流程定义[{}]中包含交接用户[{}]，开始执行替换操作", processId, handoverUserId);

            // 递归替换所有节点中的交接用户
            boolean hasReplacement = replaceAllUserInNodeModel(rootNode, handoverUserId, heirUserId, heirFlowCreator);

            if (hasReplacement) {
                // 将更新后的模型转换回JSON并保存
                String updatedModelContent = FlowLongContext.toJson(processModel.cleanParentNode());

                FlwProcess updateProcess = new FlwProcess();
                updateProcess.setId(processId);
                updateProcess.setModelContent(updatedModelContent);
                int updateCount = flwProcessMapper.updateById(updateProcess);

                if (updateCount > 0) {
                    log.info("流程定义[{}]模型更新成功，已替换所有交接用户", processId);
                    return true;
                } else {
                    log.warn("流程定义[{}]模型更新失败，可能流程不存在", processId);
                    return false;
                }
            } else {
                log.info("流程定义[{}]模型中未找到交接用户，无需更新", processId);
                return false;
            }

        } catch (Exception e) {
            log.error("更新流程定义[{}]模型失败", processId, e);
            // 这里可以考虑是否需要抛出异常来回滚整个事务
            throw new RuntimeException("更新流程定义模型失败: " + processId, e);
        }
    }

    /**
     * 更新所有正在执行的实例模型中的交接用户
     */
    private boolean updateAllRunningInstancesModel(Long processId, String handoverUserId, String heirUserId, FlowCreator heirFlowCreator) {
        try {
            // 查询该流程正在执行的实例（flw_instance表中的都是正在进行的）
            List<FlwInstance> runningInstances = flwInstanceMapper.selectList(
                    Wrappers.<FlwInstance>lambdaQuery()
                            .eq(FlwInstance::getProcessId, processId)
            );

            if (CollectionUtils.isEmpty(runningInstances)) {
                log.info("流程[{}]没有正在执行的实例", processId);
                return true;
            }

            log.info("流程[{}]有{}个正在执行的实例需要处理", processId, runningInstances.size());

            for (FlwInstance instance : runningInstances) {
                updateSingleInstanceAllUsers(instance, handoverUserId, heirUserId, heirFlowCreator);
            }
            return true;

        } catch (Exception e) {
            log.error("更新流程[{}]正在执行实例模型失败", processId, e);
            // 这里可以考虑是否需要抛出异常来回滚整个事务
            throw e;
        }
    }

    /**
     * 更新单个实例模型中的所有交接用户
     */
    private void updateSingleInstanceAllUsers(FlwInstance instance, String handoverUserId, String heirUserId, FlowCreator heirFlowCreator) {
        try {
            Long instanceId = instance.getId();

            log.info("开始更新实例[{}]模型，交接人[{}] -> 继承人[{}]",
                    instanceId, handoverUserId, heirUserId);

            // 查询实例扩展信息
            FlwExtInstance extInstance = flwExtInstanceMapper.selectById(instanceId);
            if (extInstance == null || extInstance.getModelContent() == null) {
                log.warn("实例[{}]扩展信息不存在或模型内容为空", instanceId);
                return;
            }

            // 使用ModelHelper解析实例模型
            ProcessModel processModel = ModelHelper.buildProcessModel(extInstance.getModelContent());
            NodeModel rootNode = processModel.getNodeConfig();

            // 先验证交接用户是否确实存在于该实例模型中（与query方法保持一致的逻辑）
            Long handoverUserIdLong = Long.valueOf(handoverUserId);
            if (!isContainUser(rootNode, handoverUserIdLong)) {
                log.warn("实例[{}]模型中不包含交接用户[{}]，跳过交接", instanceId, handoverUserId);
                return;
            }

            log.info("验证通过：实例[{}]模型中包含交接用户[{}]，开始执行替换操作", instanceId, handoverUserId);

            // 替换所有节点中的交接用户
            boolean hasReplacement = replaceAllUserInNodeModel(rootNode, handoverUserId, heirUserId, heirFlowCreator);

            if (hasReplacement) {
                // 将更新后的模型转换回JSON并保存
                String updatedModelContent = FlowLongContext.toJson(processModel.cleanParentNode());

                FlwExtInstance updateExtInstance = new FlwExtInstance();
                updateExtInstance.setId(instanceId);
                updateExtInstance.setModelContent(updatedModelContent);
                int updateCount = flwExtInstanceMapper.updateById(updateExtInstance);

                if (updateCount > 0) {
                    log.info("实例[{}]模型更新成功，已替换所有交接用户", instanceId);
                } else {
                    log.warn("实例[{}]模型更新失败，可能实例不存在", instanceId);
                }
            } else {
                log.info("实例[{}]模型中未找到交接用户，无需更新", instanceId);
            }

        } catch (Exception e) {
            log.error("更新实例[{}]模型失败", instance.getId(), e);
            // 这里可以考虑是否需要抛出异常来回滚整个事务
            throw new RuntimeException("更新实例模型失败: " + instance.getId(), e);
        }
    }

    /**
     * 递归替换节点模型中的所有交接用户
     */
    private boolean replaceAllUserInNodeModel(NodeModel nodeModel, String handoverUserId, String heirUserId, FlowCreator heirFlowCreator) {
        if (nodeModel == null) {
            return false;
        }

        boolean hasReplacement = false;

        // 处理当前节点的审批人
        if (replaceNodeModelAssignees(nodeModel, handoverUserId, heirUserId)) {
            hasReplacement = true;
        }

        // 处理子节点
        NodeModel childNode = nodeModel.getChildNode();
        if (childNode != null) {
            if (replaceAllUserInNodeModel(childNode, handoverUserId, heirUserId, heirFlowCreator)) {
                hasReplacement = true;
            }
        }

        // 处理并行分支
        List<ConditionNode> parallelNodes = nodeModel.getParallelNodes();
        if (!CollectionUtils.isEmpty(parallelNodes)) {
            for (ConditionNode parallelNode : parallelNodes) {
                NodeModel parallelChildNode = parallelNode.getChildNode();
                if (parallelChildNode != null) {
                    if (replaceAllUserInNodeModel(parallelChildNode, handoverUserId, heirUserId, heirFlowCreator)) {
                        hasReplacement = true;
                    }
                }
            }
        }

        // 处理条件分支
        List<ConditionNode> conditionNodes = nodeModel.getConditionNodes();
        if (!CollectionUtils.isEmpty(conditionNodes)) {
            for (ConditionNode conditionNode : conditionNodes) {
                NodeModel conditionChildNode = conditionNode.getChildNode();
                if (conditionChildNode != null) {
                    if (replaceAllUserInNodeModel(conditionChildNode, handoverUserId, heirUserId, heirFlowCreator)) {
                        hasReplacement = true;
                    }
                }
            }
        }

        // 处理包容分支
        List<ConditionNode> inclusiveNodes = nodeModel.getInclusiveNodes();
        if (!CollectionUtils.isEmpty(inclusiveNodes)) {
            for (ConditionNode inclusiveNode : inclusiveNodes) {
                NodeModel inclusiveChildNode = inclusiveNode.getChildNode();
                if (inclusiveChildNode != null) {
                    if (replaceAllUserInNodeModel(inclusiveChildNode, handoverUserId, heirUserId, heirFlowCreator)) {
                        hasReplacement = true;
                    }
                }
            }
        }

        return hasReplacement;
    }

    /**
     * 替换节点模型审批人信息
     */
    private boolean replaceNodeModelAssignees(NodeModel nodeModel, String handoverUserId, String heirUserId) {
        List<NodeAssignee> nodeAssigneeList = nodeModel.getNodeAssigneeList();
        if (CollectionUtils.isEmpty(nodeAssigneeList)) {
            return false;
        }

        boolean hasReplacement = false;
        boolean heirExists = false;
        NodeAssignee handoverAssignee = null;

        // 先检查继承人是否已经在节点中，同时找到交接人
        for (NodeAssignee assignee : nodeAssigneeList) {
            if (heirUserId.equals(assignee.getId())) {
                heirExists = true;
            }
            if (handoverUserId.equals(assignee.getId())) {
                handoverAssignee = assignee;
            }
        }

        // 如果找到了交接人
        if (handoverAssignee != null) {
            if (heirExists) {
                // 继承人已存在，直接删除交接人
                nodeAssigneeList.remove(handoverAssignee);
                hasReplacement = true;
                log.info("节点[{}]中继承人[{}]已存在，删除交接人[{}]",
                        nodeModel.getNodeKey(), heirUserId, handoverUserId);
            } else {
                // 继承人不存在，将交接人替换为继承人
                handoverAssignee.setId(heirUserId);
                SysUser user = sysUserService.getById(heirUserId);
                handoverAssignee.setName(user.getNickName());
                Map<String, Object> extendConfig = handoverAssignee.getExtendConfig();
                if (null == extendConfig) {
                    extendConfig = new HashMap<>();
                    extendConfig.put("avatar", user.getAvatar());
                } else {
                    extendConfig.put("avatar", user.getAvatar());
                }
                hasReplacement = true;
                log.info("节点[{}]中交接人[{}]已替换为继承人[{}]",
                        nodeModel.getNodeKey(), handoverUserId, heirUserId);
            }
        }

        if (hasReplacement) {
            log.info("节点[{}]审批人交接完成，继承人已存在: {}", nodeModel.getNodeKey(), heirExists);
        }

        return hasReplacement;
    }

    /**
     * 交接用户发起的流程实例
     *
     * @param userInitiatedInstances 用户发起的实例列表
     * @param heirFlowCreator        继承人
     * @return 实际成功交接的实例数量
     */
    private int handleInitiatedInstancesHandover(List<Long> userInitiatedInstances, FlowCreator heirFlowCreator) {
        if (CollectionUtils.isEmpty(userInitiatedInstances)) {
            log.debug("用户发起的实例为空，跳过交接");
            return 0;
        }

        log.info("开始交接用户发起的流程实例，继承人[{}]，共{}个实例",
                heirFlowCreator.getCreateId(), userInitiatedInstances.size());

        flwInstanceMapper.update(Wrappers.<FlwInstance>lambdaUpdate()
                .set(FlwInstance::getCreateId, heirFlowCreator.getCreateId())
                .set(FlwInstance::getCreateBy, heirFlowCreator.getCreateBy())
                .in(FlwInstance::getId, userInitiatedInstances));
        flwHisInstanceMapper.update(Wrappers.<FlwHisInstance>lambdaUpdate()
                .set(FlwHisInstance::getCreateId, heirFlowCreator.getCreateId())
                .set(FlwHisInstance::getCreateBy, heirFlowCreator.getCreateBy())
                .in(FlwHisInstance::getId, userInitiatedInstances));

        log.info("用户发起的流程实例交接完成，成功交接{}个实例", userInitiatedInstances.size());
        return userInitiatedInstances.size();
    }

    /**
     * 交接用户待办任务
     *
     * @param userPendingTasks 用户待办任务列表
     * @param handoverUser     交接人
     * @param heirUser         继承人
     * @return 实际成功交接的任务数量
     */
    private int handlePendingTasksHandover(List<Long> userPendingTasks, FlowCreator handoverUser, FlowCreator heirUser) {
        if (CollectionUtils.isEmpty(userPendingTasks)) {
            log.debug("用户待办任务为空，跳过交接");
            return 0;
        }

        log.info("开始交接用户待办任务，交接人[{}] -> 继承人[{}]，共{}个任务",
                handoverUser.getCreateId(), heirUser.getCreateId(), userPendingTasks.size());

        FlowLongEngine flowLongEngine = SpringHelper.getBean(FlowLongEngine.class);
        if (null == flowLongEngine) {
            log.error("流程引擎为空，无法进行任务交接");
            throw new RuntimeException("流程引擎服务不可用");
        }
        TaskService taskService = flowLongEngine.taskService();
        if (null == taskService) {
            log.error("任务服务为空，无法进行任务交接");
            throw new RuntimeException("任务服务不可用");
        }

        // 处理重复任务：如果继承人已经有相同的taskId，则删除交接人的任务，不再添加新任务
        List<Long> tasksToProcess = filterDuplicateTasks(userPendingTasks, handoverUser, heirUser);

        log.info("过滤重复任务后，实际需要交接的任务数量: {}", tasksToProcess.size());

        int successCount = 0;
        for (Long pendingTask : tasksToProcess) {
            try {
                taskService.transferTask(pendingTask, handoverUser, heirUser);
                successCount++;
                log.info("交接任务[{}]成功", pendingTask);
            } catch (Exception e) {
                log.error("交接待处理任务[{}]失败", pendingTask, e);
                // 这里可以考虑是否需要抛出异常来回滚整个事务
                // throw new RuntimeException("交接待处理任务失败: " + pendingTask.getTaskId(), e);
            }
        }

        log.info("用户待办任务交接完成，成功交接{}个任务", successCount);
        return successCount;
    }

    /**
     * 过滤重复任务：如果继承人已经有相同的taskId，则删除交接人的任务，不再添加新任务
     *
     * @param userPendingTasks 用户待处理任务列表
     * @param handoverUser     交接人
     * @param heirUser         继承人
     * @return 过滤后需要实际交接的任务列表
     */
    private List<Long> filterDuplicateTasks(List<Long> userPendingTasks,
                                            FlowCreator handoverUser, FlowCreator heirUser) {
        if (CollectionUtils.isEmpty(userPendingTasks)) {
            return userPendingTasks;
        }

        String handoverUserId = handoverUser.getCreateId();
        String heirUserId = heirUser.getCreateId();

        log.info("开始过滤重复任务，交接人[{}] -> 继承人[{}]", handoverUserId, heirUserId);

        // 获取继承人当前的所有待处理任务
        Set<Long> heirTaskIds = getHeirExistingTaskIds(heirUserId);
        log.info("继承人[{}]当前已有{}个待处理任务", heirUserId, heirTaskIds.size());

        List<Long> tasksToProcess = new ArrayList<>();
        ArrayList<Long> duplicateTask = new ArrayList<>();

        for (Long taskId : userPendingTasks) {

            if (heirTaskIds.contains(taskId)) {
                // 继承人已经有相同的taskId，删除交接人的任务参与者记录
                duplicateTask.add(taskId);
            } else {
                // 继承人没有该任务，需要进行正常交接
                tasksToProcess.add(taskId);
            }
        }
        if (!CollectionUtils.isEmpty(duplicateTask)) {
            // 删除交接人的任务参与者记录
            flwTaskActorMapper.delete(
                    Wrappers.<FlwTaskActor>lambdaQuery()
                            .eq(FlwTaskActor::getTaskId, duplicateTask)
                            .eq(FlwTaskActor::getActorType, ACTOR_TYPE_USER)
                            .eq(FlwTaskActor::getActorId, handoverUserId));
            log.info("删除交接人[{}]的任务参与者记录成功，共{}个任务", handoverUserId, duplicateTask.size());
        }

        log.info("任务过滤完成：总任务数[{}]，重复任务数[{}]，，需要交接任务数[{}]",
                userPendingTasks.size(), duplicateTask.size(), tasksToProcess.size());

        return tasksToProcess;
    }

    /**
     * 获取继承人当前的所有待处理任务ID
     *
     * @param heirUserId 继承人用户ID
     * @return 继承人的任务ID集合
     */
    private Set<Long> getHeirExistingTaskIds(String heirUserId) {
        try {
            List<FlwTaskActor> heirTaskActors = flwTaskActorMapper.selectList(
                    Wrappers.<FlwTaskActor>lambdaQuery()
                            .eq(FlwTaskActor::getActorType, ACTOR_TYPE_USER)
                            .eq(FlwTaskActor::getActorId, heirUserId)
            );

            return heirTaskActors.stream()
                    .map(FlwTaskActor::getTaskId)
                    .collect(Collectors.toSet());
        } catch (Exception e) {
            log.error("获取继承人[{}]的待处理任务失败", heirUserId, e);
            return new HashSet<>();
        }
    }


    /**
     * 按枚举类型组织交接查询结果
     */
    private List<HandoverQueryVO> buildHandoverQueryResults(Long userId,
                                                            Map<String, List<FlwProcess>> processTypeMap,
                                                            QueryPrefetchContext prefetchContext) {
        log.info("开始构建用户[{}]的交接查询结果, 涉及{}个工作流类型", userId, processTypeMap.size());

        List<HandoverQueryVO> results = new ArrayList<>();

        // 按枚举类型分组处理
        for (Map.Entry<String, List<FlwProcess>> entry : processTypeMap.entrySet()) {
            String workflowTypeCode = entry.getKey();
            List<FlwProcess> processes = entry.getValue();

            // 获取枚举对应的名称
            WorkflowTypeEnum workflowTypeEnum = Arrays.stream(WorkflowTypeEnum.values())
                    .filter(enumItem -> enumItem.getCode().equals(workflowTypeCode))
                    .findFirst()
                    .orElse(null);

            String categoryName = workflowTypeEnum != null ? workflowTypeEnum.getMsg() : "未知类型";

            log.debug("处理工作流类型[{}({})]下的{}个流程", categoryName, workflowTypeCode, processes.size());

            // 获取该类型下的流程ID
            List<Long> typeProcessIds = processes.stream()
                    .map(FlwProcess::getId)
                    .distinct()
                    .toList();

            // 构建流程映射
            Map<Long, FlwProcess> processMap = processes.stream()
                    .collect(Collectors.toMap(FlwProcess::getId, item -> item));

            // 构建HandoverTask数据
            HandoverQueryVO.HandoverTask handoverTask = buildHandoverTaskByType(
                    userId, typeProcessIds, processMap, categoryName, prefetchContext);

            // 计算可交接任务总数
            int handoverNum = calculateHandoverNum(handoverTask);

            // 只有存在可交接任务时才添加到结果中
            if (handoverNum > 0) {
                HandoverQueryVO result = new HandoverQueryVO();

                result.setCategoryName(categoryName);
                result.setHandoverNum(handoverNum);
                result.setHandoverTask(handoverTask);

                results.add(result);

                log.info("类型[{}]有{}个可交接任务 (包含用户的流程定义:{}, 用户发起的实例:{}, 用户待办任务:{})",
                        categoryName, handoverNum,
                        handoverTask.getContainUserProcesses().size(),
                        handoverTask.getUserInitiatedInstances().size(),
                        handoverTask.getUserPendingTasks().size());
            } else {
                log.debug("类型[{}]无可交接任务，跳过", categoryName);
            }
        }

        log.info("用户[{}]共有{}个工作流类型存在可交接任务", userId, results.size());
        return results;
    }


    /**
     * 构建交接任务数据 - 按枚举类型分别查询三种类型的任务
     */
    private HandoverQueryVO.HandoverTask buildHandoverTaskByType(Long userId, List<Long> typeProcessIds,
                                                                 Map<Long, FlwProcess> processMap,
                                                                 String categoryName,
                                                                 QueryPrefetchContext prefetchContext) {
        HandoverQueryVO.HandoverTask handoverTask = new HandoverQueryVO.HandoverTask();

        // 分别查询三种类型的任务，支持独立交接
        List<HandoverQueryVO.ProcessCategoryInfo> containUserProcesses =
                getContainUserProcessesByType(userId, typeProcessIds, processMap, categoryName);
        List<HandoverQueryVO.ProcessInstanceInfo> userInitiatedInstances =
                getUserInitiatedInstancesByType(userId, typeProcessIds, processMap, categoryName, prefetchContext);
        List<HandoverQueryVO.PendingTaskInfo> userPendingTasks =
                getUserPendingTasksByType(userId, typeProcessIds, processMap, categoryName, prefetchContext);

        handoverTask.setContainUserProcesses(containUserProcesses);
        handoverTask.setUserInitiatedInstances(userInitiatedInstances);
        handoverTask.setUserPendingTasks(userPendingTasks);

        log.info("类型[{}] - 任务统计: 包含用户的流程[{}], 用户发起的实例[{}], 用户待办任务[{}]",
                categoryName, containUserProcesses.size(), userInitiatedInstances.size(), userPendingTasks.size());

        return handoverTask;
    }

    /**
     * 计算可交接任务总数
     */
    private int calculateHandoverNum(HandoverQueryVO.HandoverTask handoverTask) {
        return handoverTask.getContainUserProcesses().size() +
                handoverTask.getUserInitiatedInstances().size() +
                handoverTask.getUserPendingTasks().size();
    }

    /**
     * 递归判断流程中是否包含该用户
     *
     * @param nodeModel 节点模型
     * @param userId    用户ID
     * @return 是否包含该用户
     */
    public Boolean isContainUser(NodeModel nodeModel, Long userId) {
        if (nodeModel == null) {
            return false;
        }

        // 检查当前节点的分配人员
        if (checkNodeAssignees(nodeModel, userId)) {
            return true;
        }

        // 根据节点类型进行不同的处理
        int nodeType = nodeModel.getType();

        // 并行节点处理
        if (TaskType.parallelBranch.getValue() == nodeType) {
            return handleParallelBranch(nodeModel, userId);
        }

        // 条件分支节点处理
        if (TaskType.conditionBranch.getValue() == nodeType) {
            return handleConditionBranch(nodeModel, userId);
        }

        // 包容分支节点处理
        if (TaskType.inclusiveBranch.getValue() == nodeType) {
            return handleInclusiveBranch(nodeModel, userId);
        }

        // 检查子节点
        return checkChildNode(nodeModel, userId);
    }

    /**
     * 检查节点分配人员是否包含指定用户
     */
    private boolean checkNodeAssignees(NodeModel nodeModel, Long userId) {
        List<NodeAssignee> nodeAssigneeList = nodeModel.getNodeAssigneeList();
        if (CollectionUtils.isEmpty(nodeAssigneeList)) {
            return false;
        }

        String userIdStr = String.valueOf(userId);
        return nodeAssigneeList.stream()
                .anyMatch(assignee -> userIdStr.equals(assignee.getId()));
    }

    /**
     * 处理并行分支节点
     */
    private boolean handleParallelBranch(NodeModel nodeModel, Long userId) {
        boolean isContain = false;

        // 检查并行分支
        List<ConditionNode> parallelNodes = nodeModel.getParallelNodes();
        if (!CollectionUtils.isEmpty(parallelNodes)) {
            for (ConditionNode parallelNode : parallelNodes) {
                if (isContainUser(parallelNode.getChildNode(), userId)) {
                    isContain = true;
                    break;
                }
            }
        }

        // 检查后续节点
        return isContain || checkChildNode(nodeModel, userId);
    }

    /**
     * 处理条件分支节点
     */
    private boolean handleConditionBranch(NodeModel nodeModel, Long userId) {
        boolean isContain = false;

        // 检查条件分支
        List<ConditionNode> conditionNodes = nodeModel.getConditionNodes();
        if (!CollectionUtils.isEmpty(conditionNodes)) {
            for (ConditionNode conditionNode : conditionNodes) {
                if (isContainUser(conditionNode.getChildNode(), userId)) {
                    isContain = true;
                    break;
                }
            }
        }

        // 检查后续节点
        return isContain || checkChildNode(nodeModel, userId);
    }

    /**
     * 处理包容分支节点
     */
    private boolean handleInclusiveBranch(NodeModel nodeModel, Long userId) {
        boolean isContain = false;

        // 检查包容分支
        List<ConditionNode> inclusiveNodes = nodeModel.getInclusiveNodes();
        if (!CollectionUtils.isEmpty(inclusiveNodes)) {
            for (ConditionNode inclusiveNode : inclusiveNodes) {
                if (isContainUser(inclusiveNode.getChildNode(), userId)) {
                    isContain = true;
                    break;
                }
            }
        }

        // 检查后续节点
        return isContain || checkChildNode(nodeModel, userId);
    }

    /**
     * 检查子节点
     */
    private boolean checkChildNode(NodeModel nodeModel, Long userId) {
        NodeModel childNode = nodeModel.getChildNode();
        return childNode != null && isContainUser(childNode, userId);
    }


    /**
     * 获取或缓存流程模型
     */
    private ProcessModel getProcessModel(FlwProcess process) {
        if (process == null || process.getModelContent() == null) {
            return null;
        }

        return processModelCache.computeIfAbsent(process.getId(), k -> {
            log.debug("解析流程[{}]的模型内容", process.getProcessName());
            return ModelHelper.buildProcessModel(process.getModelContent());
        });
    }


    /**
     * 获取包含该用户的流程定义（按类型）
     */
    private List<HandoverQueryVO.ProcessCategoryInfo> getContainUserProcessesByType(Long userId, List<Long> processIds,
                                                                                    Map<Long, FlwProcess> processMap,
                                                                                    String categoryName) {
        log.debug("类型[{}] - 开始查找包含用户[{}]的流程定义, 共{}个流程需检查", categoryName, userId, processIds.size());

        List<HandoverQueryVO.ProcessCategoryInfo> result = new ArrayList<>();
        int checkedCount = 0;
        int containCount = 0;

        for (Long processId : processIds) {
            checkedCount++;
            FlwProcess process = processMap.get(processId);

            if (process == null) {
                log.warn("类型[{}] - 流程[{}]不存在，跳过检查", categoryName, processId);
                continue;
            }

            if (process.getModelContent() == null) {
                log.warn("类型[{}] - 流程[{}({})]模型内容为空，跳过检查", categoryName, process.getProcessName(), processId);
                continue;
            }

            try {
                ProcessModel processModel = getProcessModel(process);
                if (processModel == null) {
                    log.warn("类型[{}] - 流程[{}({})]模型解析失败，跳过检查", categoryName, process.getProcessName(), processId);
                    continue;
                }

                NodeModel rootNode = processModel.getNodeConfig();
                if (isContainUser(rootNode, userId)) {
                    containCount++;
                    HandoverQueryVO.ProcessCategoryInfo info = new HandoverQueryVO.ProcessCategoryInfo();
                    info.setProcessId(processId);
                    info.setProcessName(process.getProcessName());
                    info.setProcessVersion(process.getProcessVersion());

                    result.add(info);

                    log.debug("类型[{}] - 流程[{}({})]包含用户[{}]", categoryName, process.getProcessName(), processId, userId);
                }
            } catch (Exception e) {
                log.error("类型[{}] - 检查流程[{}({})]是否包含用户[{}]时发生异常", categoryName, process.getProcessName(), processId, userId, e);
            }
        }

        log.info("类型[{}] - 包含用户流程统计：用户[{}]在{}个流程中被检查，其中{}个流程包含该用户",
                categoryName, userId, checkedCount, containCount);
        return result;
    }

    /**
     * 获取该用户发起的流程实例（按类型）
     */
    private List<HandoverQueryVO.ProcessInstanceInfo> getUserInitiatedInstancesByType(Long userId, List<Long> processIds,
                                                                                      Map<Long, FlwProcess> processMap,
                                                                                      String categoryName,
                                                                                      QueryPrefetchContext prefetchContext) {
        log.debug("类型[{}] - 查询用户[{}]发起的流程实例(使用预取数据), 涉及{}个流程", categoryName, userId, processIds.size());

        Set<Long> targetProcessIds = new HashSet<>(processIds);
        List<FlwInstance> instances = CollectionUtils.isEmpty(prefetchContext.userInitiatedInstancesAll)
                ? Collections.emptyList()
                : prefetchContext.userInitiatedInstancesAll.stream()
                .filter(inst -> targetProcessIds.contains(inst.getProcessId()))
                .toList();

        log.debug("类型[{}] - 用户[{}]共发起了{}个流程实例(过滤后)", categoryName, userId, instances.size());

        List<HandoverQueryVO.ProcessInstanceInfo> result = new ArrayList<>();

        for (FlwInstance instance : instances) {
            try {
                HandoverQueryVO.ProcessInstanceInfo info = new HandoverQueryVO.ProcessInstanceInfo();
                info.setInstanceId(instance.getId());
                info.setProcessId(instance.getProcessId());
                info.setInstanceNo(instance.getInstanceNo());
                info.setCurrentNodeName(instance.getCurrentNodeName());

                // 格式化创建时间
                if (instance.getCreateTime() != null) {
                    info.setCreateTime(instance.getCreateTime().toString());
                }

                // 获取流程信息
                FlwProcess process = processMap.get(instance.getProcessId());
                if (process != null) {
                    info.setProcessName(process.getProcessName());
                } else {
                    log.warn("类型[{}] - 实例[{}]对应的流程[{}]不存在", categoryName, instance.getId(), instance.getProcessId());
                    info.setProcessName("未知流程");
                }

                result.add(info);

                log.debug("类型[{}] - 处理实例[{}({})] - 流程: {}, 当前节点: {}",
                        categoryName, instance.getInstanceNo(), instance.getId(),
                        info.getProcessName(), instance.getCurrentNodeName());

            } catch (Exception e) {
                log.error("类型[{}] - 处理用户[{}]发起的实例[{}]时发生异常", categoryName, userId, instance.getId(), e);
            }
        }

        log.info("类型[{}] - 用户发起实例统计：用户[{}]发起的可交接流程实例数量: {}", categoryName, userId, result.size());
        return result;
    }

    /**
     * 获取需要该用户审批的任务（按类型）
     */
    private List<HandoverQueryVO.PendingTaskInfo> getUserPendingTasksByType(Long userId, List<Long> processIds,
                                                                            Map<Long, FlwProcess> processMap,
                                                                            String categoryName,
                                                                            QueryPrefetchContext prefetchContext) {
        log.debug("类型[{}] - 查询用户[{}]的待处理任务(使用预取数据), 涉及{}个流程", categoryName, userId, processIds.size());

        // 1. 使用预取的参与记录
        List<FlwTaskActor> taskActors = prefetchContext.taskActors;
        if (CollectionUtils.isEmpty(taskActors)) {
            log.debug("类型[{}] - 用户[{}]无任何待处理任务", categoryName, userId);
            return new ArrayList<>();
        }

        // 2. 使用预取的任务与实例
        List<FlwTask> allTasks = CollectionUtils.isEmpty(prefetchContext.tasksFromActors)
                ? Collections.emptyList()
                : prefetchContext.tasksFromActors;
        List<FlwInstance> allInstances = CollectionUtils.isEmpty(prefetchContext.instancesFromTasks)
                ? Collections.emptyList()
                : prefetchContext.instancesFromTasks;

        if (CollectionUtils.isEmpty(allTasks) || CollectionUtils.isEmpty(allInstances)) {
            log.debug("类型[{}] - 用户[{}]的任务或实例为空", categoryName, userId);
            return new ArrayList<>();
        }

        // 3. 过滤出属于指定流程类型的实例和任务
        Set<Long> targetProcessIds = new HashSet<>(processIds);
        List<FlwInstance> filteredInstances = allInstances.stream()
                .filter(instance -> targetProcessIds.contains(instance.getProcessId()))
                .toList();

        if (CollectionUtils.isEmpty(filteredInstances)) {
            log.debug("类型[{}] - 用户[{}]在指定流程中无运行实例", categoryName, userId);
            return new ArrayList<>();
        }

        Set<Long> filteredInstanceIds = filteredInstances.stream()
                .map(FlwInstance::getId)
                .collect(Collectors.toSet());

        List<FlwTask> filteredTasks = allTasks.stream()
                .filter(task -> filteredInstanceIds.contains(task.getInstanceId()))
                .toList();

        log.debug("类型[{}] - 过滤后找到{}个相关流程实例，{}个相关任务",
                categoryName, filteredInstances.size(), filteredTasks.size());

        // 4. 构建结果
        List<HandoverQueryVO.PendingTaskInfo> result = buildPendingTaskInfosByType(filteredTasks, filteredInstances, processMap, categoryName);

        log.info("类型[{}] - 用户待办任务统计：用户[{}]的待处理任务数量: {}", categoryName, userId, result.size());
        return result;
    }

    /**
     * 查询预取上下文
     */
    private static class QueryPrefetchContext {
        Set<Long> allProcessIds;
        // 用户作为参与者的任务链路
        List<FlwTaskActor> taskActors;
        List<FlwTask> tasksFromActors;
        List<FlwInstance> instancesFromTasks;
        // 用户发起的实例（限定在本次涉及的流程）
        List<FlwInstance> userInitiatedInstancesAll;
    }

    /**
     * 构建待处理任务信息列表（按类型）
     */
    private List<HandoverQueryVO.PendingTaskInfo> buildPendingTaskInfosByType(List<FlwTask> tasks,
                                                                              List<FlwInstance> instances,
                                                                              Map<Long, FlwProcess> processMap,
                                                                              String categoryName) {
        List<HandoverQueryVO.PendingTaskInfo> result = new ArrayList<>();
        Map<Long, FlwInstance> instanceMap = instances.stream()
                .collect(Collectors.toMap(FlwInstance::getId, item -> item));

        for (FlwTask task : tasks) {
            try {
                HandoverQueryVO.PendingTaskInfo info = new HandoverQueryVO.PendingTaskInfo();
                info.setTaskId(task.getId());
                info.setInstanceId(task.getInstanceId());
                info.setTaskName(task.getTaskName());

                // 格式化创建时间
                if (task.getCreateTime() != null) {
                    info.setCreateTime(task.getCreateTime().toString());
                }

                // 获取实例信息
                FlwInstance instance = instanceMap.get(task.getInstanceId());
                if (instance != null) {
                    info.setProcessId(instance.getProcessId());
                    info.setInstanceNo(instance.getInstanceNo());

                    // 获取流程信息
                    FlwProcess process = processMap.get(instance.getProcessId());
                    if (process != null) {
                        info.setProcessName(process.getProcessName());
                    } else {
                        log.warn("类型[{}] - 任务[{}]对应的流程[{}]不存在", categoryName, task.getId(), instance.getProcessId());
                        info.setProcessName("未知流程");
                    }
                } else {
                    log.warn("类型[{}] - 任务[{}]对应的实例[{}]不存在", categoryName, task.getId(), task.getInstanceId());
                }

                result.add(info);

                log.debug("类型[{}] - 处理待办任务[{}({})] - 流程: {}, 实例: {}",
                        categoryName, task.getTaskName(), task.getId(),
                        info.getProcessName(), info.getInstanceNo());

            } catch (Exception e) {
                log.error("类型[{}] - 构建任务[{}]信息时发生异常", categoryName, task.getId(), e);
            }
        }

        return result;
    }
}
